package com.avalon.erp.sys.addon.base.controller;

import com.avalon.core.condition.Condition;
import com.avalon.core.context.Context;
import com.avalon.core.exception.AvalonException;
import com.avalon.core.exception.FieldCheckException;
import com.avalon.core.exception.RedisLockException;
import com.avalon.core.field.SelectionField;
import com.avalon.core.model.*;
import com.avalon.core.model.Record;
import com.avalon.core.redis.IRedisLock;
import com.avalon.core.redis.RedisCommon;
import com.avalon.core.service.AbstractService;
import com.avalon.core.util.ObjectUtils;
import com.avalon.core.util.RecordRowUtils;
import com.avalon.core.util.StringUtils;
import com.avalon.erp.sys.addon.base.model.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.List;

@RestController
@RequestMapping("/model")
@Slf4j
public class ServiceController {

    @Resource
    private Context context;
    @Resource
    private RedisCommon redisCommon;

    @PostMapping("add")
    public RecordRow addModel(@RequestBody ServiceModelParam param) throws AvalonException {
        AbstractService serviceBean = context.getServiceBean(param.getServiceName());
        RecordRow recordRow = RecordRowUtils.convert(serviceBean, param.getValue());

        PrimaryKey id = serviceBean.insert(recordRow);
        recordRow = new RecordRow();
        recordRow.put("id", id);
        return recordRow;
    }

    @PostMapping("update")
    public RecordRow updateModel(@RequestBody ServiceModelParam param) throws AvalonException {
        AbstractService serviceBean = context.getServiceBean(param.getServiceName());
        RecordRow recordRow = RecordRowUtils.convert(serviceBean, param.getValue());

        String serviceName = serviceBean.getServiceName();
        serviceName = serviceName.replace(".", ":") + "update";
        serviceName += ":" + recordRow.getString(serviceBean.getPrimaryKeyName());
        IRedisLock lock = redisCommon.getLock(serviceName);
        Boolean aBoolean = lock.tryLock(10);
        Integer rows = 0;
        if (aBoolean) {
            try {
                rows = serviceBean.update(recordRow);
            } finally {
                lock.unlock();
            }

        } else {
            throw new RedisLockException();
        }

        recordRow = new RecordRow();
        recordRow.put("row", rows);
        return recordRow;
    }

    /**
     * 伪删除 status: enable -> disable
     *
     * @return
     * @throws AvalonException
     */
    @PostMapping("pseudo")
    public RecordRow pseudoModel(@RequestBody ServiceModelId param) throws AvalonException {
        AbstractService serviceBean = context.getServiceBean(param.getServiceName());
        RecordRow recordRow = serviceBean.selectOne(Integer.parseInt(param.getId().toString()));
        if (ObjectUtils.isNull(recordRow)) {
            throw new FieldCheckException("数据不存在,无法删除");
        }

        RecordRow updateRow = new RecordRow();
        updateRow.put("id", recordRow.get("id").getValue());

        if (ObjectUtils.isNotNull(serviceBean.getField("isDelete"))) {
            updateRow.put("isDelete", true);
            Integer row = serviceBean.update(updateRow);
            recordRow = new RecordRow();
            recordRow.put("row", row);
            return recordRow;
        }

        throw new FieldCheckException("删除失败");
    }

    @PostMapping("delete")
    public RecordRow deleteModel(@RequestBody ServiceModelId param) throws AvalonException {
        AbstractService serviceBean = context.getServiceBean(param.getServiceName());
        RecordRow recordRow = serviceBean.selectOne(Integer.parseInt(param.getId().toString()));
        if (ObjectUtils.isNull(recordRow)) {
            throw new FieldCheckException("数据不存在,无法删除");
        }
        String serviceName = serviceBean.getServiceName();
        serviceName = serviceName.replace(".", ":") + "delete";
        serviceName += ":" + param.getId();
        IRedisLock lock = redisCommon.getLock(serviceName);
        Boolean aBoolean = lock.tryLock(10);
        Integer row = 0;
        if (aBoolean) {
            try {
                row = serviceBean.delete(recordRow);
            } finally {
                lock.unlock();
            }
        } else {
            throw new RedisLockException();
        }


        recordRow = new RecordRow();
        recordRow.put("row", row);
        return recordRow;
    }

    @PostMapping("get/fields")
    public RecordRow getModelFieldList(@RequestBody ServiceModelFieldList serviceModelFieldList) throws AvalonException {
        List serviceList = serviceModelFieldList.getServiceList();

        Record record = new Record();

        serviceList.forEach(service -> {

            AbstractService serviceBean = context.getServiceBean(service.toString());
            FieldHashMap relationFieldMap = serviceBean.getRelationFieldMap();

            serviceBean.getFieldMap().forEach((s, field) -> {
                if (!relationFieldMap.containsKey(field)) {
                    RecordRow recordRow = new RecordRow();
                    recordRow.put("filedLabel", field.getLabel());
                    recordRow.put("filedName", field.getName());
                    record.add(recordRow);
                }
            });
        });

        RecordRow result = new RecordRow();
        result.put("data", record);

        return result;
    }

    /**
     * description: 获取serviceBean 里面的 selection 值，没有做传值判断
     * version: 1.0
     * date: 2022/4/8 9:13
     * author: AN
     *
     * @param param
     * @return com.avalon.core.model.RecordRow
     */
    @PostMapping("get/selection/map")
    public RecordRow getSelection(@RequestBody ServiceModelField param) {
        AbstractService serviceBean = context.getServiceBean(param.getServiceName());
        RecordRow row = new RecordRow();

        SelectionField selectionField = (SelectionField) serviceBean.getField(param.getFields());
        Record record = new Record();
        selectionField.getSection().forEach(((o, s) -> {
            RecordRow row1 = new RecordRow();
            row1.put("id", o);
            row1.put("name", s);
            record.add(row1);
        }));

        row.put("data", record);
        return row;
    }

    @PostMapping("get/list")
    public RecordRow getList(@RequestBody ServiceModelList param) throws AvalonException {
        AbstractService serviceBean = context.getServiceBean(param.getServiceName());
        RecordRow recordRow = new RecordRow();
        if (ObjectUtils.isNotEmpty(param.getCondition())) {
            recordRow.put("data", serviceBean.selectList(param.getFields(), param.getCondition()));
        } else {
            recordRow.put("data", serviceBean.selectList(param.getFields(), param.getRpnCondition()));
        }
        return recordRow;
    }

    @PostMapping("get/detail")
    public RecordRow getDetail(@RequestBody ServiceModelField param) throws AvalonException {
        AbstractService serviceBean = context.getServiceBean(param.getServiceName());
        RecordRow selectOne = null;
        Condition condition = null;
        if (ObjectUtils.isNotNull(param.getId())) {
            condition = Condition.equalCondition(serviceBean.getPrimaryKeyName(),
                    param.getId());
        } else if (ObjectUtils.isNotEmpty(param.getCondition())) {
            condition = serviceBean.getConditionByHighListCondition(param.getCondition());
        } else {
            condition = Condition.parseRPN(param.getRpnCondition());
        }

        if (StringUtils.isEmpty(param.getFields())) {
            selectOne = serviceBean.selectOne(condition);
        } else {
            selectOne = serviceBean.selectOne(param.getFields(), condition);
        }

        return selectOne;
    }

    /**
     * 获取第一条数据
     *
     * @param serviceConditionPage
     * @return
     */
    @PostMapping("get/one")
    public RecordRow getOne(@RequestBody ServiceConditionHighPage serviceConditionPage) {
        AbstractService serviceBean = context.getServiceBean(serviceConditionPage.getServiceName());

        if (ObjectUtils.isNotEmpty(serviceConditionPage.getCondition())) {
            return serviceBean.selectOneNoLevel(serviceConditionPage.getFields(),
                    serviceConditionPage.getCondition(),
                    serviceConditionPage.getOrder());
        } else {
            return serviceBean.selectOneNoLevel(serviceConditionPage.getFields(),
                    Condition.parseRPN(serviceConditionPage.getRpnCondition()),
                    serviceConditionPage.getOrder());
        }
    }

    /**
     * 获取全部数据
     *
     * @param serviceConditionPage
     * @return
     */
    @PostMapping("get/all")
    public Record getAll(@RequestBody ServiceConditionHighPage serviceConditionPage) {
        AbstractService serviceBean = context.getServiceBean(serviceConditionPage.getServiceName());

        if (ObjectUtils.isNotEmpty(serviceConditionPage.getCondition())) {
            return serviceBean.select(serviceConditionPage.getFields(),
                    serviceConditionPage.getCondition());
        } else {
            return serviceBean.select(serviceConditionPage.getFields(),
                    Condition.parseRPN(serviceConditionPage.getRpnCondition()));
        }
    }

    @PostMapping("/get/page/condition")
    public PageInfo getPage(@RequestBody ServiceConditionPage serviceConditionPage) throws AvalonException {
        AbstractService serviceBean = context.getServiceBean(serviceConditionPage.getServiceName());
        if (ObjectUtils.isNotEmpty(serviceConditionPage.getCondition())) {
            return serviceBean.selectPageCondition(serviceConditionPage.getPage(),
                    serviceConditionPage.getFields(),
                    serviceConditionPage.getOrder(),
                    serviceConditionPage.getIsDistinct(),
                    serviceConditionPage.getCondition());
        } else {
            return serviceBean.selectPage(serviceConditionPage.getPage(),
                    serviceConditionPage.getFields(),
                    serviceConditionPage.getOrder(),
                    serviceConditionPage.getIsDistinct(),
                    Condition.parseRPN(serviceConditionPage.getRpnCondition()));
        }
    }

    @PostMapping("/get/page/condition/high")
    public PageInfo getPage(@RequestBody ServiceConditionHighPage serviceConditionPage) throws AvalonException {
        AbstractService serviceBean = context.getServiceBean(serviceConditionPage.getServiceName());
        if (ObjectUtils.isNotEmpty(serviceConditionPage.getCondition())) {
            return serviceBean.selectPageConditionHigh(serviceConditionPage.getPage(),
                    serviceConditionPage.getFields(),
                    serviceConditionPage.getOrder(),
                    serviceConditionPage.getIsDistinct(),
                    serviceConditionPage.getCondition());
        } else {
            return serviceBean.selectPage(serviceConditionPage.getPage(),
                    serviceConditionPage.getFields(),
                    serviceConditionPage.getOrder(),
                    serviceConditionPage.getIsDistinct(),
                    Condition.parseRPN(serviceConditionPage.getRpnCondition()));
        }
    }

    @PostMapping("/get/page/condition/object")
    public PageInfo getPageObject(@RequestBody ServiceConditionHighPage serviceConditionPage) {
        AbstractService serviceBean = context.getServiceBean(serviceConditionPage.getServiceName());
        if (ObjectUtils.isNotEmpty(serviceConditionPage.getCondition())) {
            return serviceBean.selectPageWithObjectExtend(serviceConditionPage.getPage(),
                    serviceConditionPage.getFields(),
                    serviceConditionPage.getOrder(),
                    serviceConditionPage.getIsDistinct(),
                    serviceConditionPage.getCondition());
        } else {
            return serviceBean.selectPageWithObject(serviceConditionPage.getPage(),
                    serviceConditionPage.getFields(),
                    serviceConditionPage.getOrder(),
                    serviceConditionPage.getIsDistinct(),
                    Condition.parseRPN(serviceConditionPage.getRpnCondition()));
        }
    }

    @PostMapping("get/tree/page/condition")
    public PageInfo getTreePage(@RequestBody ServiceConditionHighPage serviceConditionPage) {
        AbstractService serviceBean = context.getServiceBean(serviceConditionPage.getServiceName());
        if (ObjectUtils.isNotEmpty(serviceConditionPage.getCondition())) {
            return serviceBean.selectTreePageCondition(serviceConditionPage.getPage(),
                    serviceConditionPage.getFields(),
                    serviceConditionPage.getOrder(),
                    serviceConditionPage.getCondition());
        } else {
            return serviceBean.selectTreePage(serviceConditionPage.getPage(),
                    serviceConditionPage.getFields(),
                    serviceConditionPage.getOrder(),
                    Condition.parseRPN(serviceConditionPage.getRpnCondition()));
        }
    }
}
